<template>

  <el-button type="primary" @click="add()" v-hasPermission="'user:add'">添加用户</el-button>
  <el-button type="danger"  @click="batchRemove()" v-hasPermission="'user:remove'">批量删除</el-button>

  <!-- 用户列表 -->
  <!--
    :data="userList"  单向绑定表格数据

    @selection-change="handleSelectionChange"   选择改变事件
      勾选或者取消勾选复选框时触发该函数
      注意：这个函数使用的时候不需要加括号，函数触发时会自动传入参数，参数是勾选了复选框的选项数组
  -->
  <el-table
      :data="userList"
      style="width: 100%"
      @selection-change="handleSelectionChange">

    <!-- type="selection" 复选框 -->
    <el-table-column type="selection" width="55" />
    <!-- type="index"  序号以1递增 -->
    <el-table-column type="index" label="序号" width="60" />
    <!-- 要想当页面宽度改变时，展示数据的不换行，可以给el-table-column标签单独设置宽度 -->
    <el-table-column property="loginAct" label="账号" width="120" />
    <el-table-column property="name" label="姓名" width="120" />
    <el-table-column property="phone" label="手机" />
    <el-table-column property="email" label="邮箱" />
    <el-table-column property="createTime" label="创建时间" />
    <el-table-column property="lastLoginTime" label="最后登录时间" />
    <el-table-column label="操作" width="240" >
      <!-- 作用域插槽 -->
      <template #default="scope">
        <!-- scope.row.id  获取当前行上数据对象的id -->
        <el-button type="primary" @click="detail(scope.row.id)" v-hasPermission="'user:detail'">详情</el-button>
        <el-button type="success" @click="edit(scope.row.id)"   v-hasPermission="'user:edit'"  >编辑</el-button>
        <el-button type="danger"  @click="remove(scope.row.id)" v-hasPermission="'user:remove'">删除</el-button>
      </template>
    </el-table-column>
  </el-table>

  <!--
    分页功能
      layout="prev, pager, next"  组件布局，子组件名用逗号分隔  prev, pager, next, jumper, ->, total
      @prev-click="toPage" 点击上一页触发函数
      @next-click="toPage" 点击下一页触发函数
      @current-change="toPage"  当前页发生改变时触发函数
      注意：这里的函数不要加括号，element-plus会自动传递一个参数（当前页数）
  -->
  <el-pagination
      background
      layout="prev, pager, next"
      :page-size="this.pageSize"
      :total="this.total"
      @prev-click="toPage"
      @next-click="toPage"
      @current-change="toPage"/>

  <!-- 用户信息的弹窗（对话框） -->
  <!--
    v-model                值为true时，显示对话框，false隐藏对话框
    center                 内容居中
    draggable              可拖拽的对话框
    :close-on-click-modal  是否可以通过点击对话框外的页面关闭对话框
    :destroy-on-close      对话框关闭时，是否销毁其中元素（例如：验证规则的提示信息）
    :title                 添加用户和编辑用户共用一个对话框，所以标题这里是动态的（title属性单向绑定），当编辑用户的时候一定查询了用户信息，所以用户id一定大于0
  -->
  <el-dialog
      v-model="userDialogVisible"
      :title="this.userQuery.id > 0 ? '编辑用户' : '添加用户'"
      width="55%"  center  draggable
      :close-on-click-modal="false"
      :destroy-on-close="true">

    <!-- :model="userQuery"   表单绑定的数据 -->
    <!-- label-width="110px"  表单整体距离左侧的宽度 -->
    <!-- :rules="userRules"   绑定验证规则 -->
    <!-- ref="userRefForm"    表单提交之前验证表单的验证规则 -->
    <el-form :model="userQuery" label-width="110px" :rules="userRules" ref="userRefForm">
      <!-- prop="loginAct" 要验证的内容 -->
      <el-form-item label="账号" prop="loginAct">
        <!-- v-model.trim  去除前后空格 -->
        <el-input v-model.trim="userQuery.loginAct" />
      </el-form-item>

      <!-- 渲染密码输入框（编辑用户） -->
      <!-- 前端不验证密码规则（后端验证），因为后端返回的密码是加密后的密码，在不更改密码的情况下前端无法通过验证，影响用户体验 -->
      <!-- v-if="this.userQuery.id > 0"  当用户id大于0时渲染，点击编辑按钮的时候查询了用户信息，用户id一定大于0 -->
      <el-form-item label="密码" v-if="this.userQuery.id > 0">
        <!-- v-model.trim  去除前后空格 -->
        <el-input type="password" v-model.trim="userQuery.loginPwd" placeholder="不显示密码，在此框内输入内容即视为修改密码，密码为6-12位的数字" />
      </el-form-item>

      <!-- 渲染密码输入框（添加用户） -->
      <!-- 前端验证密码规则 -->
      <el-form-item label="密码" prop="loginPwd" v-else>
        <el-input type="password" v-model.trim="userQuery.loginPwd" />
      </el-form-item>

      <el-form-item label="姓名" prop="name">
        <el-input v-model="userQuery.name" />
      </el-form-item>

      <el-form-item label="手机" prop="phone">
        <el-input v-model="userQuery.phone" />
      </el-form-item>

      <el-form-item label="邮箱" prop="email">
        <el-input v-model="userQuery.email" />
      </el-form-item>

      <el-form-item label="账号是否过期" prop="accountNoExpired">
        <el-select v-model="userQuery.accountNoExpired" placeholder="请选择">
          <!-- 这里el-option的value单向绑定，当编辑用户时，后端返回该属性的值为 1或0 ，此时根据该属性的值来显示相对应的信息 -->
          <el-option label="未过期" :value="1" />
          <el-option label="已过期" :value="0" />
        </el-select>
      </el-form-item>

      <el-form-item label="密码是否过期" prop="credentialsNoExpired">
        <el-select v-model="userQuery.credentialsNoExpired" placeholder="请选择">
          <el-option label="未过期" :value="1" />
          <el-option label="已过期" :value="0" />
        </el-select>
      </el-form-item>

      <el-form-item label="账号是否锁定" prop="accountNoLocked">
        <el-select v-model="userQuery.accountNoLocked" placeholder="请选择">
          <el-option label="未锁定" :value="1" />
          <el-option label="已锁定" :value="0" />
        </el-select>
      </el-form-item>

      <el-form-item label="账号是否启用" prop="accountEnabled">
        <el-select v-model="userQuery.accountEnabled" placeholder="请选择">
          <el-option label="已启用" :value="1" />
          <el-option label="未启用" :value="0" />
        </el-select>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <!-- 根据用户不同的操作调用不同的执行方法 -->
        <el-button type="primary" @click="this.userQuery.id > 0 ? editUserSubmit() : addUserSubmit()">提交</el-button>
        <el-button @click="userDialogVisible = false">关闭</el-button>
      </div>
    </template>
  </el-dialog>

</template>

<script>
import {doDelete, doGet, doPost, doPut} from "../http/httpRequest.js";
import {messageConfirm, messageTip} from "../util/util.js";

  export default {
    // 组件名
    name: "UserView",

    // 注入父级页面提供的数据
    inject: ['reload'],

    data() {
      return {
        // 用户列表，注意：是数组，不是对象，数组中的每个值都是一个对象
        userList: [{}],

        pageSize: 0,  // 每页条数
        total: 0,     // 总条数

        // 设置用户信息的对话框是否可见
        userDialogVisible: false,

        // 用户信息对象
        userQuery: { },

        // 用户信息的验证规则
        userRules: {
          // 定义验证规则，规则可以有多个，所以是数组
          loginAct: [
            // required: true   不能为空
            // message          提示信息
            // trigger: 'blur'  光标离开时触发规则
            { required: true, message: '请输入账号', trigger: 'blur' }
          ],
          loginPwd: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            // 密码验证的正则
            { pattern: /^\d{6,12}$/, message: '密码为6-12位的数字', trigger: 'blur' }
          ],
          name: [
            { required: true, message: '请输入姓名', trigger: 'blur' },
            // pattern  验证正则表达式
            { pattern: /^[\u4E00-\u9FA5]{0,}$/, message: '姓名必须是中文', trigger: 'blur' }
          ],
          phone: [
            { required: true, message: '请输入手机号', trigger: 'blur' },
            // 手机号验证的正则
            { pattern: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/, message: '手机号格式不正确', trigger: 'blur' }
          ],
          email: [
            { required: true, message: '请输入邮箱', trigger: 'blur' },
            // 邮箱验证的正则
            // @之前必须有内容且只能是字母（大小写）、数字、下划线(_)、减号（-）、点（.）
            // @和最后一个点（.）之间必须有内容且只能是字母（大小写）、数字、点（.）、减号（-），且两个点不能挨着
            // 最后一个点（.）之后必须有内容且内容只能是字母（大小写）、数字且长度为大于等于2个字节，小于等于6个字节
            { pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/, message: '邮箱格式不正确', trigger: 'blur' }
          ],
          accountNoExpired: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          credentialsNoExpired: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          accountNoLocked: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          accountEnabled: [
            { required: true, message: '请选择', trigger: 'blur' }
          ]
        },

        // 批量删除用户的id数组
        userIdArray: []
      }
    },

    // 钩子函数，页面渲染完成后自动执行
    mounted() {
      // 页面渲染完成后查询第一页用户
      this.getUserList(1);
    },

    methods: {
      // 勾选或者取消勾选复选框时触发该函数，并自动传入参数（选项数组）
      handleSelectionChange(selectionItemArray) {
        // 每次触发该函数后，先将存放id的数组清空，然后再添加数据，以保证数据真实性，避免重复
        this.userIdArray = [];

        // 遍历选项数组
        selectionItemArray.forEach(data => {
          // data就是选择的某条数据（用户），取出用户id，添加到用户id数组当中
          let userId = data.id;
          this.userIdArray.push(userId)
        })
      },

      // 查询用户列表
      getUserList(current) {
        doGet("/api/user/list", {
          // 当前查询第几页
          current: current
        }).then( (resp) => {
          if (resp.data.code === 200) {
            this.userList = resp.data.data.list;      // 用户列表
            this.pageSize = resp.data.data.pageSize;  // 每页条数
            this.total = resp.data.data.total;        // 总条数
          } else {
            messageTip("用户列表获取失败", "error");
          }
        })
      },

      // 分页函数，当前页数发生改变时触发
      toPage(current) {
        // current这个参数是element-plus自动传过来，当前页数
        this.getUserList(current)
      },

      // 用户详情
      detail(id) {
        // 跳转到路由
        this.$router.push("/dashboard/user/detail/" + id);
      },

      // 添加用户按钮
      add() {
        // 弹出对话框之前，先给用户信息对象赋空对象，清空对话框的内容
        // 编辑对象时会查询用户信息并给userQuery对象赋值，会携带用户信息展示
        this.userQuery = { };
        // 点击添加用户按钮，弹出用户信息的对话框
        this.userDialogVisible = true;
      },

      // 添加用户提交保存
      addUserSubmit() {
        // 点击提交按钮后，验证数据是否符合规则
        this.$refs.userRefForm.validate( (isValid) => {
          // 如果验证的结果isValid为true，则执行以下代码
          if (isValid) {
            // 参数较多，通过FormData对象传参
            let formData = new FormData();
            // 获取用户填写的数据，遍历获取user对象的属性名
            for (let field in this.userQuery) {
              // field 属性名，this.user[field] 通过属性名获取属性值
              // 向FormData对象中添加用户信息
              formData.append(field, this.userQuery[field])
            }
            // 向后端发送请求
            doPost("/api/user/add", formData).then( (resp) => {
              if (resp.data.code === 200) {
                messageTip("提交成功", "success");
                // 关闭对话框
                this.userDialogVisible = false;
                // 刷新用户列表页面（通过路由组件的展示和隐藏，来达到刷新页面的目的）
                this.reload();
                // 刷新用户列表页面（重新查询用户列表，获取数据后会重新渲染，这种方式会发送一次请求，占用网络资源）
                // this.getUserList(1);
              } else {
                messageTip("提交失败", "error");
              }
            })
          }
        })
      },

      // 编辑用户按钮
      edit(id) {
        // 加载用户信息
        this.loadUser(id);

        // 弹出用户信息对话框（编辑用户和添加用户共用一个对话框）
        this.userDialogVisible = true;
      },

      // 加载用户信息（编辑用户时对话框所需要）
      loadUser(id) {
        // 向后端发送请求获取该用户的信息，并显示到对话框内
        doGet("/api/user/detail/" + id, { }).then( (resp) => {
          if (resp.data.code === 200) {
            // 将后端返回的数据赋值给用户信息对象
            this.userQuery = resp.data.data;
            // 将密码框清空
            this.userQuery.loginPwd = "";
          } else {
            messageTip("该用户信息获取失败", "error")
          }
        })
      },

      // 编辑用户提交保存
      editUserSubmit() {
        // 验证表单规则
        this.$refs.userRefForm.validate( (isValid) => {
          // 判断验证是否通过
          if (isValid) {
            // 创建FormData对象，使用该对象传参
            let formData = new FormData();
            // 遍历用户信息对象，获取属性名
            for (let field in this.userQuery) {
              // 通过属性名获取属性值，给FormData对象添加数据
              formData.append(field, this.userQuery[field]);
            }
            // 向后端发送请求
            doPut("/api/user/edit", formData).then( (resp) => {
              if (resp.data.code === 200) {
                messageTip("编辑成功", "success");
                // 关闭对话框
                this.userDialogVisible = false;
                // 刷新用户列表
                this.reload();
              } else {
                messageTip("提交失败，原因：" + resp.data.msg, "error");
              }
            })
          }
        })
      },

      // 删除用户
      remove(id) {
        // 弹出确认框
        messageConfirm("确认删除该用户吗?").then(() => {
          // 向后端发送请求
          doDelete("/api/user/remove/" + id, { }).then( (resp) => {
            if (resp.data.code === 200) {
              messageTip("删除成功", "success");
              // 刷新用户列表
              this.reload();
            } else {
              messageTip("删除失败，原因：" + resp.data.msg, "error")
            }
          })
        }).catch(() => {
          messageTip("取消删除", "warning");
        })
      },

      // 批量删除
      batchRemove() {
        // 判断用户id数组中是否有数据
        if (this.userIdArray.length > 0) {
          // 弹出确认框
          messageConfirm("确认批量删除这些用户吗?").then(() => {
            // 直接使用数组作为参数，会报错（浏览器控制台会显示存在跨域问题）
            // 原来是数组 userIdArray = [1,2,5,6,7]  通过join(",")方法  变成字符串 ids = "1,2,5,6,7"
            let ids = this.userIdArray.join(",");
            // 向后端发送请求
            doDelete("/api/user/batchRemove", {
              ids: ids
            }).then( (resp) => {
              if (resp.data.code === 200) {
                messageTip("批量删除成功", "success");
                // 刷新用户列表页面
                this.reload();
              } else {
                messageTip("批量删除失败，原因：" + resp.data.msg, "error");
              }
            })
          }).catch(() => {
            messageTip("取消批量删除", "warning");
          })
        } else {
          messageTip("没有选择数据", "warning");
        }
      }
    }
  }
</script>

<style scoped>

  /* 表格 */
  .el-table {
    margin-top: 20px;   /* 上边距 */
  }

  /* 分页栏 */
  .el-pagination {
    margin-top: 20px;   /* 上边距 */
  }

</style>

